package com.abu.apply.service.impl;

import cn.hutool.core.util.StrUtil;
import com.abu.apply.client.CourseClient;
import com.abu.apply.client.ManagerClient;
import com.abu.apply.config.mvc.LoginInterceptor;
import com.abu.apply.mapper.ApplyReportMapper;
import com.abu.apply.service.ApplyReportService;
import com.abu.apply.vo.*;
import com.abu.common.Resp;
import com.abu.common.exception.CRException;
import com.abu.apply.pojo.ApplyReport;
import com.abu.course.vo.ClassroomOrderVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 申请记录表 服务实现类
 * </p>
 *
 * @author 阿布
 * @since 2021-02-03
 */
@Service
public class ApplyReportServiceImpl extends ServiceImpl<ApplyReportMapper, ApplyReport> implements ApplyReportService {

    @Autowired
    private ApplyReportMapper applyReportMapper;

    @Autowired
    private ManagerClient managerClient;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private CourseClient courseClient;

    private static final String CHECKED_EXCHANGE = "CHECKED_EXCHANGE";
    private static final String CHECKED_ROUTINGKEY = "CHECKED_ROUTINGKEY";


    @Override
    public HashMap<String, Object> queryApplyByPage(QueryApplyReportVo queryApplyReportVo) {
//        构建分页条件
        Long limit = queryApplyReportVo.getLimit();
        Long page = queryApplyReportVo.getPage();
//       不同数字代表不同column
        Integer type = queryApplyReportVo.getType();
        String key = queryApplyReportVo.getKey();
        Integer applyStatus = queryApplyReportVo.getApplyStatus();
        String column = null;
        if (type != null) {
            switch (type) {
                case 1:
                    column = "applicant_email";
                    break;
                case 2:
                    column = "classroom_name";
                    break;
                case 3:
                    column = "applicant";
                    break;
                default:
                    break;
            }
        }
//        获取当前用户登录的id
        String managerId = LoginInterceptor.getManagerId();
//        分页条件
        Page<ApplyReport> reportPage = new Page<>(page, limit);
        QueryWrapper<ApplyReport> reportQueryWrapper = new QueryWrapper<>();
        reportQueryWrapper
                .like(column != null, column, key)
                .eq(!StrUtil.equals(managerId, "1"), "reviewer_id", managerId)
                .eq(applyStatus != null, "apply_status", applyStatus);
//        执行查询
        Page<ApplyReport> applyReportPage = this.applyReportMapper.selectPage(reportPage, reportQueryWrapper);
//        获取总条数
        long total = applyReportPage.getTotal();
//       封装结果集
        List<ApplyReport> applyReportList = applyReportPage.getRecords();
        List<ApplyReportVO> applyReportVOList = applyReportList.stream().map(applyReport -> {
            ApplyReportVO applyReportVO = new ApplyReportVO();
            Resp resp = this.managerClient.getManagerByReviewerId(applyReport.getReviewerId());
            Integer code = resp.getCode();
            String msg = resp.getMsg();
            if (code == 503) {
                throw new CRException(msg, code);
            }
            LinkedHashMap managerMap = (LinkedHashMap) resp.getData().get("manager");
//            获取管理员名字
            String name = (String) managerMap.get("realName");
            applyReportVO.setReviewer(name);
            BeanUtils.copyProperties(applyReport, applyReportVO);
            return applyReportVO;
        }).collect(Collectors.toList());
        //        获取结果集
        HashMap<String, Object> mapResult = new HashMap<>(2);
        mapResult.put("applyReportVOList", applyReportVOList);
        mapResult.put("total", total);
        return mapResult;
    }

    @Override
    public boolean updateState(Long applyId, Integer status) {
//        获取管理员登录名
        String managerId = LoginInterceptor.getManagerId();
        ApplyReportVO applyReportVO = new ApplyReportVO();
        applyReportVO
                .setReviewerId(managerId)
                .setApplyId(applyId)
                .setApplyStatus(status)
                .setReviewerTime(LocalDateTime.now());
        int count = this.applyReportMapper.updateById(applyReportVO);
        ApplyReport applyReport = this.getById(applyId);

//        获取更新后的数据
        HashMap<String, Object> map = new HashMap(4);
        map.put("applicant", applyReport.getApplicant());
        map.put("classroomName", applyReport.getClassroomName());
        map.put("applyStatus", applyReport.getApplyStatus());
        map.put("email", applyReport.getApplicantEmail());

        try {
            this.rabbitTemplate.convertAndSend(CHECKED_EXCHANGE, CHECKED_ROUTINGKEY, map);
        } catch (AmqpException e) {
            throw new CRException("消息发送失败");
        }
        return count == 1;
    }

    @Override
    public Integer queryNonInspectApplyReport(Long reviewerId, Integer status) {
//        管理员id =1 可查询所有
        if (reviewerId == 1) {
            return this.applyReportMapper.selectCount(new QueryWrapper<ApplyReport>().eq("apply_status", status));
        }
//        其他的按照id查看
        QueryWrapper<ApplyReport> queryWrapper = new QueryWrapper<ApplyReport>()
                .eq("reviewer_id", reviewerId)
                .eq("apply_status", status);
        return this.applyReportMapper.selectCount(queryWrapper);
    }

    @Override
    public HashMap<String, Object> getTypes() {
        List<ResultTypes> typesList = this.applyReportMapper.selectTypes();
        List<ResultTypes> resultTypesList = typesList.stream().map((resultTypes -> {
            String status = resultTypes.getStatus();
            switch (status) {
                case "0":
                    resultTypes.setName("待审核");
                    break;
                case "1":
                    resultTypes.setName("审核通过");
                    break;
                case "2":
                    resultTypes.setName("已驳回");
                    break;
                default:
                    break;
            }
            return resultTypes;
        })).collect(Collectors.toList());

        List<String> nameList = resultTypesList.stream().map(ResultTypes::getName).collect(Collectors.toList());
        List<Integer> valList = resultTypesList.stream().map(ResultTypes::getValue).collect(Collectors.toList());
        HashMap<String, Object> map = new HashMap<>(2);
        map.put("nameList", nameList);
        map.put("valList", valList);
        return map;
    }

    @Override
    public HashMap<String, Object> selectByPage(QueryConditionSelect queryConditionSelect) {
        List<ApplyReport> applyReportList = null;
        LocalDateTime beginTime = queryConditionSelect.getBeginTime();
        LocalDateTime endTime = queryConditionSelect.getEndTime();
        String classroomName = queryConditionSelect.getName();
        HashMap<String, Object> hashMap = null;
//        按时间条件查询
        if (beginTime != null && endTime != null) {
            if (endTime.isBefore(beginTime)) {
                throw new CRException("结束时间 要大于 开始时间", 400);
            }
            applyReportList = this.applyReportMapper.selectPageByCondition(classroomName, beginTime, endTime);
            Integer total = this.applyReportMapper.selectCountByCondition(classroomName, beginTime, endTime);
            if (CollectionUtils.isEmpty(applyReportList)) {
                throw new CRException("当前教室没有被预约过", 404);
            }
            hashMap = new HashMap<>(2);
//        查询一共多少条
            hashMap.put("total", total);
            hashMap.put("applyReportList", applyReportList);
            return hashMap;
        }
        return hashMap;
    }

    @Override
    public HashMap<String, Object> queryPageByCondition(QueryConditionSelect queryConditionSelect) {
        Long page = queryConditionSelect.getPage();
        Long size = queryConditionSelect.getSize();
        String classroomName = queryConditionSelect.getName();
        HashMap<String, Object> hashMap = new HashMap<>(2);
//            普通分页查询所有
        List<ApplyReport> applyReportList = this.applyReportMapper.selectPages(page, size, classroomName);
        if (CollectionUtils.isEmpty(applyReportList)) {
            throw new CRException("数据为空", 404);
        }
        Integer total = this.applyReportMapper.selectTotalSimple(classroomName);
//        查询一共多少条
        hashMap.put("total", total);
        hashMap.put("applyReportList", applyReportList);
        return hashMap;
    }

    @Override
    public HashMap<String, Object> queryApplyListByUserId(Long currentPage, Long limit, String key) {
        QueryWrapper<ApplyReport> queryWrapper = new QueryWrapper<>();
        Long userId = LoginInterceptor.getUserInfo().getUserId();
        queryWrapper.eq("user_id", userId);
        if (!StringUtils.isEmpty(key)) {
            queryWrapper.eq("classroom_name", key);
        }
        Page<ApplyReport> applyReportPage = new Page<>(currentPage, limit);
        Page<ApplyReport> pageResult = this.page(applyReportPage, queryWrapper);
//        获取总记录
        List<ApplyReport> applyReportList = pageResult.getRecords();
//        获取总数
        long resultTotal = pageResult.getTotal();
        if (CollectionUtils.isEmpty(applyReportList)) {
            throw new CRException("数据为空", 404);
        }
        List<ApplyReportVO> applyReportVOList = applyReportList.stream().map(applyReport -> {
//            属性copy
            ApplyReportVO applyReportVO = new ApplyReportVO();
            BeanUtils.copyProperties(applyReport, applyReportVO);
//            计算课程时长（分钟）
            LocalDateTime beginTime = applyReport.getBeginTime();
            LocalDateTime endTime = applyReport.getEndTime();
            Duration duration = Duration.between(beginTime, endTime);
            long durationMinutes = duration.getSeconds() / 60;
            applyReportVO.setInterval(durationMinutes);
//            获取审核人的名字
            String reviewerId = applyReport.getReviewerId();
            Resp resp = this.managerClient.getManagerByReviewerId(reviewerId);
//            判断服务是否可用（网络不通则走fallback方法）
            String msg = resp.getMsg();
            Integer code = resp.getCode();
            if (code == 503) {
                throw new CRException(msg, code);
            }
            LinkedHashMap managerMap = (LinkedHashMap) resp.getData().get("manager");
            String mgName = (String) managerMap.get("realName");
            applyReportVO.setReviewer(mgName);
            return applyReportVO;
        }).collect(Collectors.toList());
//        数据返回
        HashMap<String, Object> map = new HashMap<>(2);
        map.put("total", resultTotal);
        map.put("applyReportVOList", applyReportVOList);
        return map;
    }

    @Override
    public List<ApplyReport> queryCourseAndApplyHistory(String classroomName) {
//        查询当前教室所有预定记录
        QueryWrapper<ApplyReport> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("classroom_name", classroomName).select("applicant", "begin_time", "end_time", "used_reason");
        List<ApplyReport> applyReportList = this.list(queryWrapper);
//        查询当前教室所有课程记录
        Resp resp = this.courseClient.getClassroomOrderByClassroomName(classroomName);
        ArrayList courseArrayList = (ArrayList) resp.getData().get("courseList");
        if (!CollectionUtils.isEmpty(courseArrayList)) {
            courseArrayList.forEach(courseMap -> {
                LinkedHashMap map = (LinkedHashMap) courseMap;
                ApplyReport applyReport = new ApplyReport();
                String beginTimeStr = (String) map.get("beginTime");
                String endTimeStr = (String) map.get("endTime");
                LocalDateTime beginTime = LocalDateTime.parse(beginTimeStr);
                LocalDateTime endTime = LocalDateTime.parse(endTimeStr);
                applyReport
                        .setApplicant(map.get("applicant").toString())
                        .setBeginTime(beginTime)
                        .setEndTime(endTime)
                        .setUsedReason(map.get("usedReason").toString());
                applyReportList.add(applyReport);
            });

        }
//        返回结果集
        return applyReportList;

    }

    @Override
    public List<ApplyStatusCountVO> selectAllCount() {
//        1.获取管理员名称
        String managerId = LoginInterceptor.getManagerId();
//        2.执行查询
        List<ApplyStatusCountVO> applyStatusCountVOList = this.applyReportMapper.selectAllStatusCount(managerId);
//        3.根据apply_status转为相应的description
        applyStatusCountVOList.forEach(applyStatusCountVO -> {
            String applyStatus = applyStatusCountVO.getApplyStatus();
            switch (applyStatus) {
                case "0":
                    applyStatusCountVO.setName("待审核");
                    break;
                case "1":
                    applyStatusCountVO.setName("审核通过");
                    break;
                case "2":
                    applyStatusCountVO.setName("已驳回");
                    break;
                default:
                    break;
            }
        });
//        返回结果集
        return applyStatusCountVOList;
    }

}
